home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
1_0-2
/
ASCII_CH
/
ASCII_CH.C
Wrap
Text File
|
1986-08-14
|
17KB
|
402 lines
/*************************************************************************/
/* Ascii Chart - a Desk Accessory for the Macintosh written by: */
/* Wade S. Blomgren (c) 1986 version 1.0 */
/* UC San Diego */
/* */
/* Both source and executable files may be freely distributed for */
/* NON-COMMERCIAL USE ONLY provided this copyright notice is left */
/* intact. */
/* */
/* This program is intended as an example for persons beginning to */
/* learn about programming the Macintosh. It is NOT meant to be an */
/* example of excellent programming or a particularly fabulous */
/* idea for a program. It IS supposed to be chock full of comments */
/* and to have some examples of common uses for the toolbox. */
/* */
/* This program was written using LightspeedC (c) from Think */
/* Technologies, INC. and therefore includes material that is */
/* copyright Think Technologies INC. */
/* */
/* Some techniques were gleaned from a PD desk accessory called */
/* ZoomIdle by Paul DuBois, University of Wisconsin */
/* */
/* Wade S. Blomgren UCSD-ACS mailcode B-028 La Jolla, CA 92093 */
/* */
/*************************************************************************/
#include "devicemgr.h"
#include "quickdraw.h"
#include "windowmgr.h"
#include "dialogmgr.h"
#include "eventmgr.h"
#include "controlmgr.h"
/* since this is a DA and not a standalone application we do not have to */
/* initialize the various managers */
/* Global Variables for the DA */
/* the chart data is stored in two dimensional arrays so we can use the */
/* drawtext routine (faster than repeated calls to drawchar) (IM I-172) */
char octdata[23][47] = {
"000 NUL 026 SYC 054 , 102 B 130 X 156 n ",
"001 SOH 027 ETB 055 - 103 C 131 Y 157 o ",
"002 STX 030 CAN 056 . 104 D 132 Z 160 p ",
"003 ETX 031 EM 057 / 105 E 133 [ 161 q ",
"004 EOT 032 SUB 060 0 106 F 134 \\ 162 r ",
"005 ENQ 033 ESC 061 1 107 G 135 ] 163 s ",
"006 ACK 034 FS 062 2 110 H 136 ^ 164 t ",
"007 BEL 035 GS 063 3 111 I 137 _ 165 u ",
"010 BS 036 RS 064 4 112 J 140 ` 166 v ",
"011 HT 037 US 065 5 113 K 141 a 167 w ",
"012 LF 040 SPA 066 6 114 L 142 b 170 x ",
"013 VT 041 ! 067 7 115 M 143 c 171 y ",
"014 FF 042 '' 070 8 116 N 144 d 172 z ",
"015 CR 043 # 071 9 117 O 145 e 173 { ",
"016 SO 044 $ 072 : 120 P 146 f 174 | ",
"017 SI 045 % 073 ; 121 Q 147 g 175 } ",
"020 DLE 046 & 074 < 122 R 150 h 176 ~ ",
"021 DC1 047 ' 075 = 123 S 151 i 177 DEL",
"022 DC2 050 ( 076 > 124 T 152 j ",
"023 DC3 051 ) 077 ? 125 U 153 k ",
"024 DC4 052 * 100 @ 126 V 154 l ",
"025 NAK 053 + 101 A 127 W 155 m "};
char decdata[23][47] = {
"000 NUL 022 SYC 044 , 066 B 088 X 110 n ",
"001 SOH 023 ETB 045 - 067 C 089 Y 111 o ",
"002 STX 024 CAN 046 . 068 D 090 Z 112 p ",
"003 ETX 025 EM 047 / 069 E 091 [ 113 q ",
"004 EOT 026 SUB 048 0 070 F 092 \\ 114 r ",
"005 ENQ 027 ESC 049 1 071 G 093 ] 115 s ",
"006 ACK 028 FS 050 2 072 H 094 ^ 116 t ",
"007 BEL 029 GS 051 3 073 I 095 _ 117 u ",
"008 BS 030 RS 052 4 074 J 096 ` 118 v ",
"009 HT 031 US 053 5 075 K 097 a 119 w ",
"010 LF 032 SPA 054 6 076 L 098 b 120 x ",
"011 VT 033 ! 055 7 077 M 099 c 121 y ",
"012 FF 034 '' 056 8 078 N 100 d 122 z ",
"013 CR 035 # 057 9 079 O 101 e 123 { ",
"014 SO 036 $ 058 : 080 P 102 f 124 | ",
"015 SI 037 % 059 ; 081 Q 103 g 125 } ",
"016 DLE 038 & 060 < 082 R 104 h 126 ~ ",
"017 DC1 039 ' 061 = 083 S 105 i 127 DEL",
"018 DC2 040 ( 062 > 084 T 106 j ",
"019 DC3 041 ) 063 ? 085 U 107 k ",
"020 DC4 042 * 064 @ 086 V 108 l ",
"021 NAK 043 + 065 A 087 W 109 m " };
char hexdata[23][47] = {
"000 NUL 016 SYC 02C , 042 B 058 X 06E n ",
"001 SOH 017 ETB 02D - 043 C 059 Y 06F o ",
"002 STX 018 CAN 02E . 044 D 05A Z 070 p ",
"003 ETX 019 EM 02F / 045 E 05B [ 071 q ",
"004 EOT 01A SUB 030 0 046 F 05C \\ 072 r ", /* escape the \ character */
"005 ENQ 01B ESC 031 1 047 G 05D ] 073 s ",
"006 ACK 01C FS 032 2 048 H 05E ^ 074 t ",
"007 BEL 01D GS 033 3 049 I 05F _ 075 u ",
"008 BS 01E RS 034 4 04A J 060 ` 076 v ",
"009 HT 01F US 035 5 04B K 061 a 077 w ",
"00A LF 020 SPA 036 6 04C L 062 b 078 x ",
"00B VT 021 ! 037 7 04D M 063 c 079 y ",
"00C FF 022 '' 038 8 04E N 064 d 07A z ",
"00D CR 023 # 039 9 05F O 065 e 07B { ",
"00E SO 024 $ 03A : 050 P 066 f 07C | ",
"00F SI 025 % 03B ; 051 Q 067 g 07D } ",
"010 DLE 026 & 03C < 052 R 068 h 07E ~ ",
"011 DC1 027 ' 03D = 053 S 069 i 07F DEL",
"012 DC2 028 ( 03E > 054 T 06A j ",
"013 DC3 029 ) 03F ? 055 U 06B k ",
"014 DC4 02A * 040 @ 056 V 06C l ",
"015 NAK 02B + 041 A 057 W 06D m " };
DCtlPtr dce; /* pointer to the device control entry struct */
int DAisOpen = 0; /* flag so we know if the DA is already open */
#define rALRT 0 /* the About box's resource ID # */
/* allocate control handles to the various control buttons */
ControlHandle OctPtr,HexPtr,DecPtr,curControl,whichControl,AbPtr;
int line; /* counter for the text drawing loop */
int y; /* coordinate variable for positioning the text */
/* define rectangles for the DA's window and the control buttons */
/* BlankRect is the entire data area & is used to erase the data */
static Rect bounds = { 60,60, 335, 350 };
static Rect OctRect = { 225,12,242,80 };
static Rect HexRect = { 225,115, 242, 185 };
static Rect DecRect = { 225,200, 242, 268 };
static Rect AbRect = { 250,85, 270, 205 };
static Rect BlankRect = { 3,12,220,280 };
/* various functions begin here - see 'main' for calling sequence */
aboutDA() /* creates an alert dialog message about */
/* the DA and gives an OK button to exit */
{
/* the alert resource and accompanying item list are stored in a */
/* file called "ascii_chart.rsrc" which was created with ResEdit */
/* ..since the OK button is the default (highlighted) choice, we */
/* do not have to have a filterProc (IM I-419) */
/* If you examine the DA file with ResEdit, you will see that the */
/* resource ID for the ALRT is -16000, which translates into an */
/* 'owned' resource ID of '0' (zero) for a DRVR (our program) */
/* with an ID of '12'. This is the ID number that LightspeedC */
/* assigns to a Desk Accesory that it creates. When you install */
/* a DA with the Font/DA mover, it checks to see that the ID# does */
/* not conflict with that of an existing DA. If it does, the F/DA */
/* will change our DA's ID to an unused #, and all of the 'owned' */
/* resource ID's will be shifted accordingly. Read IM I-108,109. */
Alert(rsrcID(rALRT),0L); /* invoke the alert (IM I-418) */
}
/* this routine from the LightspeedC demo DA by Michael Kahl... */
/* returns the correct resource ID number "no matter what driver # */
/* the Font/DA Mover has assigned us... " (IM I-109) */
rsrcID(id)
{
return(0xc000 + (~dce->dCtlRefNum << 5 ) + id);
}
/* window update routine - if it's a result of a radix change, scope */
/* is 0 (update everything) - if it is a system update event, update */
/* only the area that needs it, by using BeginUpdate & EndUpdate */
/* (see calls to 'updateDisplay()' in 'main' and 'DAEvent' */
updateDisplay(scope)
int scope;
{
GrafPtr currentPort;
Ptr dataAddr; /* a generic 'pointer' data type */
GetPort(¤tPort); /* save the current grafport (IM I-447) */
SetPort(dce->dCtlWindow); /* set the grafport to our window */
if (scope)
BeginUpdate(dce->dCtlWindow); /* set the visRgn to only the part */
/* that needs updating (IM I-292) */
/* otherwise, redraw the whole window */
DrawControls(dce->dCtlWindow); /* draw the controls in our window */
EraseRect(&BlankRect); /* blank out the old data (IM I-177) */
y = 10;
if (curControl == OctPtr) /* determine which control was pressed */
dataAddr = (Ptr) octdata; /* & cast the address of the 2D array */
else if (curControl == DecPtr) /* into our generic data pointer */
dataAddr = (Ptr) decdata;
else if (curControl == HexPtr)
dataAddr = (Ptr) hexdata;
TextFont(4); /* Monaco font for evenly spaced columns (IM I-219) */
TextSize(9); /* these are quickdraw functions */
for (line = 0; line < 22; line++) {
/* we have 23 lines per 'page' - use quickdraw to output the data */
/* the starting address for DrawText is (line# * 47) to get to the */
/* proper position in the 2D array */
MoveTo(12,y);
DrawText(dataAddr + (line * 47),0,46); /* (IM I-172) */
y = y +10;
}
if (scope) EndUpdate(dce->dCtlWindow);
SetPort(currentPort); /* restore the current grafport (IM I-447) */
} /* end of updateDisplay */
openDA() /* open the desk accessory */
{
GrafPtr currentPort;
if (DAisOpen) return; /* if it is already open, just ignore */
GetPort(¤tPort); /* save the current grafport */
/* create our window, set the device control entry (dce) window field */
/* to our window, set the window's windowKind field to the reference # */
/* for the driver (IM I-445) */
dce->dCtlWindow = NewWindow(0,&bounds,"\pAscii Chart",0,16,-1,1,0);
((WindowPeek) (dce->dCtlWindow))->windowKind = dce->dCtlRefNum;
SetPort(dce->dCtlWindow); /* set the grafport to our window */
ShowWindow(dce->dCtlWindow); /* display the window */
/* create new controls for the various radixes and the about box */
/* set the octal radix control to be 'on'... (IM I-319) */
OctPtr = NewControl(dce->dCtlWindow,&OctRect,"\poctal",1,1,0,1,2,0);
HexPtr = NewControl(dce->dCtlWindow,&HexRect,"\phex",1,0,0,1,2,0);
DecPtr = NewControl(dce->dCtlWindow,&DecRect,"\pdecimal",1,0,0,1,2,0);
AbPtr = NewControl(dce->dCtlWindow,&AbRect,"\pabout ascii chart",1,1,0,0,0,0);
curControl = OctPtr; /* set default for current control button */
/* we do not need to explicitly call "updateDisplay" because the open */
/* routine will cause an update event to be sent to the Desk Manager */
DAisOpen = 1; /* set the DA 'on' (our own flag) */
SetPort(currentPort); /* restore original grafport */
return(0);
} /* end of the openDA routine */
DAevent(theEvent)
EventRecord *theEvent; /* argument is a pointer to an event record */
{
GrafPtr currentPort;
GetPort(¤tPort); /* save the system's current grafport */
/* at this point we know there has been an event in the DA window */
/* content region, so we must process the event */
SetPort(dce->dCtlWindow); /* set the port to our window */
switch (theEvent->what) { /* examine the 'what' field of event */
/* (IM I-263,264) */
case activateEvt: /* the DA window has become active */
updateDisplay(1);
return(0);
case updateEvt: /* we need to update (result of drag, etc) */
updateDisplay(1);
return(0);
case mouseDown:
/* convert the location to local coordinates (IM I-193,323) */
GlobalToLocal(&(theEvent->where));
/* find where mouse was pressed - (the part code) (IM I-334) */
switch (FindControl(theEvent->where,dce->dCtlWindow,&whichControl)) {
case (11): /* a RADIO button has been hit - track it */
/* track control routine makes sure mouse is released in button */
if (TrackControl(whichControl,theEvent->where,0)) {
if (whichControl != curControl) { /* a new radix */
SetCtlValue(curControl,0);
curControl = whichControl; /* set new 'current' ctl */
SetCtlValue(curControl,1);
updateDisplay(0); /* update whole window */
} /* end new radix */
} /* end if track control */
break;
case (10): /* SIMPLE button (must be the about box) */
/* create an alert dialog with an OK button to terminate */
aboutDA();
break;
} /* end possible control mousedown */
LocalToGlobal(&theEvent->where); /* put the coordinates back to global */
} /* end of the event switch */
SetPort(currentPort); /* restore the grafport */
} /* end of DAevent */
/* close DA function */
closeDA()
{
GrafPtr currentPort;
GetPort(¤tPort); /* save the system's grafport */
DisposeWindow(dce->dCtlWindow);/* dispose our window */
dce->dCtlWindow = 0L; /* set the driver's window ptr to null */
/* (IM I-446) */
SetPort(currentPort); /* restore the system's grafport */
return(0);
}
/* main driver routine - three parameters are passed to us through the */
/* device manager. 1. the control parameter pointer */
/* 2. the pointer to the dce record */
/* 3. the driver routine (open, control, or close) */
/* (IM II-201, I-445 ) */
main (p,d,n)
cntrlParam *p;
DCtlPtr d;
int n;
{
if (d->dCtlStorage == 0 ) {
if (n == 0) { /* open but no data */
SysBeep(3);
CloseDriver(d->dCtlRefNum);
}
return(0);
}
dce = d;
/* find the appropriate driver routine */
switch(n) { /* 0 = open, 2 = control event, 4 = close */
case 0: /* open the DA */
openDA();
break;
case 2: /* action in the DA */
switch(p->csCode) {
case accEvent:
DAevent(((EventRecord *) * (long *) &p->csParam));
/* casting the *address of* p->csParam as an pointer to a long, and the */
/* long is cast as a pointer to a pointer to an Event Record (I think?) */
/* (from ZoomIdle 1.1 by Paul DuBois) */
/* the pointer is passed as the parameter to DAevent */
} /* end of case 2 switch */
break;
case 4: /* close box has been clicked */
closeDA();
break;
} /* end of the main switch */
return(0);
} /* end of main */